package com.hqhy.like.front.order.alipay.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.hqhy.like.common.enumerator.ServiceCode;
import com.hqhy.like.common.ex.ServiceException;
import com.hqhy.like.front.order.alipay.pojo.param.PayParam;
import com.hqhy.like.front.order.pojo.param.OrderUpdateInfoParam;
import com.hqhy.like.front.order.pojo.param.TableUpdateInfoParam;
import com.hqhy.like.front.order.pojo.vo.OrderTableVO;
import com.hqhy.like.front.order.service.IOrderService;
import com.hqhy.like.front.order.service.ITableService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import static com.hqhy.like.common.consts.data.MallConsts.*;

@Api(tags = "3. 模拟支付")
@RestController
@RequestMapping("/alipay")
@Slf4j
public class PayController {

    @Autowired
    private IOrderService orderService;

    @Autowired
    private ITableService tableService;

    /**
     * APP ID，请在支付宝沙箱应用（https://open.alipay.com/develop/sandbox/app）中查找正确的值
     */
    private static final String APP_ID = "9021000128622142";
    /**
     * 应用私钥，请在支付宝沙箱应用（https://open.alipay.com/develop/sandbox/app）中查找正确的值
     */
    private static final String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCTNkh49dKblAWPrIguFhIYA4i+jqY/veXbr80Z5HHVAeia3QoM9kzTuXgRVVWHZsJd97W4jTNcDUXFn16ilBriRcNpIQCPE2jZ3yKcxhYoAd65iqzvKrIs2w2U9YBCnXmu8H2ShT3NnJsG7AA3r975q3Z8cZWgI715cF4ttD7bJswdYQhh7TufD94lpwyVI4zozqwDyigE17+KN2/FeXxZiNB6EiWZYMigBavPXOXYFjafg1AyfJK9bOirzu18BZYyjQopV9S3ceYfzpaYOD9j3PWafLXzqq91cV5q8Hr3h/wZhs3UGFAk9skn+JcPoPoJiReYYhMH3hQlH3NxlNb9AgMBAAECggEABfx6G/kbFFqDk2EXtJAPMkzKfb09Q3BMbY+Ljpb8jgXi2JFOfFJzs1RibooCzVu/YaTWDegoA4FCqhOd/Ix7P2JI3PiLlkXayKlLNgbUFdJlpTPfbmZVEn/h4IHPMmZG8Xc0FAY5CihpIXHtXFZZgduYGN1hkT6C0PJh0gf3Wl/8stX2GUipE1WA2XL5s0v0yhsCMvUHIocQZAQbgY5CNwOk8hWkClga902a4vtcnr2HCRC3AtRV9E729H8opnWdRc0onKNmNmcXZlmvZaZ6Da2fj8MQUAfHaprTkhNqbrVsGKhvVw5UT7CjpRcgHvSrJURBeyve/LH2DtGn5+i8/QKBgQDNMHXFTzqF59YJ6wVg+33pttyNPzKI+uo6XMnuMPrGhttZiHKn3ZrHhdd47zSnZmafkW4MR4vuCL/LgVyyXcqyRm2JcYdy4rR6bY6LURQwePfVZn4l1eylM85wlo+bBjMOkt+nqWLU5jJDZtYmGDYmsjtKokAY8W6AMln8h/3Y5wKBgQC3qnpl0r7HZCyms33r7yxmxHTsuVTZxi+2pAOZDRKqLGlEDt1wGCtRXoU1/T1RvgoZo8TCePrAHfc/OQlRupciObK5H/EnKEhwQ8XhRHaaMJHRlse0nCYHuNLYnBaq59X0h9nF3hWyxBqPYuv0dwFXhp951Bf4sDuiFxwKgKFgewKBgCUDbtsu1ZG+JmAXoxrBgw8by2E3WzhWetYYUtzCvRn+zaay9GvPj9IaFKpeDBN+Z1i1dTKF3XoM3fwp07zhKmVKSwwWDKbuujuzc5kyAQBVce9u06ajllKeq8ingDQoxCEG4Y1vAsMA22RJMqwghfQpBoUKC6H0O0iozI6/QU1VAoGBAJZ3CVMFtdmvzYy8G3sANAX1CD0vD75hSJF+CJyIQzQ6sfpZmzvL8SD2KHe0gVnIMIoUyorvha2CXx3iYiocjNgzIKHc8zk7HS0ruJ718ZwcEjn8JptmGRnWZpWiOkfFKljsOpKJgIk1cvTo+5kJLYZA+cFa6lCIQDJocEaCXrKlAoGBAJ7dyh1+mK4MzTw4Oo0GlbHAwe84n3kNfq6JDVa2m9yQRcvnZOTWDJkfB7xFmgSmR7YMGoXHeKy3EUlMk3kFZolDFG9KNeDGeslyNP9Rq4UEE0PGeAHJYo9Le2Rq5kxzL+/CT40OtRWOtMIdEItEs7joh0Z35LRUpKL9mNT9yWNY";
    /**
     * 支付宝公钥，请在支付宝沙箱应用（https://open.alipay.com/develop/sandbox/app）中查找正确的值
     */
    private static final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhdA1iYaTNGgnvEFFK7zhtObyU0cQCQ97IIjLxeZ1/H7h2sN6PHLAWcXyIt7Or1FubWJEJifwuiNfTVvZ/ELgClClhxYbaqSCjkNvpJULxrLN7FyEn9oTPtCjL9vsf+6WMK0jOhOTQOxDGpHx38lX2oGqflUYaVy52bCXX9RResdfqiWcFJKEpvXx0jjTWpaKMqH1axIOnUF8y9BrunWjH8uga3N8mfd1CMW0CoGiokVTN6W+pa1aM+qB7WNrr3RIIXXXi+MbMHdJPsyO6A95pqah2IWsZgcKi9x19XznFJZmnL3GK/Du3FiJX63ZIY8TAYd6tXs7I7XUds2tqY7p2QIDAQAB";
    /**
     * 通知网址，用于处理支付宝完成支付处理后，你的应用中进行下一步处理的请求地址
     */
    private static final String NOTIFY_URL = "http://localhost:10042/alipay/notify";
    /**
     * 返回网址，用于支付宝完成支付处理后，重定向到某个位置
     */
    private static final String RETURN_URL = "http://localhost:10042/alipay/finish";

    /**
     * 【固定】支付宝网关
     */
    private static final String ALIPAY_GATEWAY = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    /**
     * 【固定】加密算法
     */
    private static final String ENCRYPTION_ALGORITHM = "RSA2";
    /**
     * 【固定】字符编码
     */
    private static final String CHARSET = "UTF-8";
    /**
     * 【固定】数据格式
     */
    private static final String DATA_FORMAT = "json";

    // 此方法用于接收客户端发起的支付请求，并响应支付表单页面到客户端
    // 网页客户端应该通过window.open直接向此处发起请求，则响应的支付表单会直接显示在window.open打开的窗口中
    @ApiOperation("支付宝沙箱支付")
    @ApiOperationSupport(order = 100)
    @GetMapping("/pay")
    public String pay(PayParam payParam, @ApiIgnore HttpServletResponse response) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(
                ALIPAY_GATEWAY, APP_ID, PRIVATE_KEY, DATA_FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, ENCRYPTION_ALGORITHM);
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //异步接收地址，仅支持http/https，公网可访问
        request.setNotifyUrl(NOTIFY_URL);
        //同步跳转地址，仅支持http/https
        request.setReturnUrl(RETURN_URL);
        /******必传参数******/
        JSONObject bizContent = new JSONObject();
        //商户订单号，商家自定义，保持唯一性
        bizContent.put("out_trade_no", payParam.getOutTradeNo());
        //支付金额，最小值0.01元
        bizContent.put("total_amount", payParam.getTotalAmount());
        //订单标题，不可使用特殊符号
        bizContent.put("subject", payParam.getSubject());
        //电脑网站支付场景固定传值FAST_INSTANT_TRADE_PAY
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");

        /******可选参数******/
        //bizContent.put("time_expire", "2022-08-01 22:00:00");

        //// 商品明细信息，按需传入
        //JSONArray goodsDetail = new JSONArray();
        //JSONObject goods1 = new JSONObject();
        //goods1.put("goods_id", "goodsNo1");
        //goods1.put("goods_name", "子商品1");
        //goods1.put("quantity", 1);
        //goods1.put("price", 0.01);
        //goodsDetail.add(goods1);
        //bizContent.put("goods_detail", goodsDetail);

        //// 扩展信息，按需传入
        //JSONObject extendParams = new JSONObject();
        //extendParams.put("sys_service_provider_id", "2088511833207846");
        //bizContent.put("extend_params", extendParams);

        request.setBizContent(bizContent.toString());
        AlipayTradePagePayResponse alipayTradePagePayResponse = alipayClient.pageExecute(request);
        if (alipayTradePagePayResponse.isSuccess()) {
            System.out.println("调用成功，将在浏览器中打开支付宝【沙箱】支付页");
            String responseBody = alipayTradePagePayResponse.getBody();
            System.out.println(responseBody);
            return responseBody;
        } else {
            return "交易失败，调用支付宝远程接口失败，请返回订单页查看订单状态，或重新支付！";
        }
    }

    // 接收支付宝发送的通知（支付结果）
    // 注意：必须是POST请求
    @ApiIgnore
    @PostMapping("/notify")
    public String payNotify(@ApiIgnore HttpServletRequest request) throws Throwable {
        log.debug("开始处理【订单支付完成】的通知请求，网页请求: {}",request);
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            params.put(name, request.getParameter(name));
        }
        String sign = params.get("sign");
        String content = AlipaySignature.getSignCheckContentV1(params);
        boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, ALIPAY_PUBLIC_KEY, CHARSET); // 验证签名
        // 支付宝验签
        if (checkSignature) {
            // 验签通过
            System.out.println("交易名称: " + params.get("subject"));
            System.out.println("交易状态: " + params.get("trade_status"));
            System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
            System.out.println("商户订单号: " + params.get("out_trade_no"));
            System.out.println("交易金额: " + params.get("total_amount"));
            System.out.println("买家支付宝ID: " + params.get("buyer_id"));
            System.out.println("买家付款时间: " + params.get("gmt_payment"));
            System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
            // 你应该在此处补充支付成功后续的代码，例如修改订单状态等
            // 完成
            return "支付完成";
        } else {
            return "支付失败，请返回订单页查看订单状态，或重新支付！";
        }
    }

    // 接收处理支付宝的跳转（支付完成后自动重定向到此处）
    @ApiIgnore
    @GetMapping("/finish")
    public String finish(String out_trade_no){
        log.debug("开始处理【订单支付完成】的请求，订单编号: {}",out_trade_no);
        OrderTableVO queryResult = orderService.getStandardByOrderNo(out_trade_no);
        if (queryResult == null) {
            String message = "更新数据错误，订单桌台数据不存在！";
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        //更新订单状态
        OrderUpdateInfoParam orderUpdateInfoParam = new OrderUpdateInfoParam();
        orderUpdateInfoParam.setOrderState(ORDER_STATE_COMPLETED_PAID);
        orderUpdateInfoParam.setPayChannel(PAY_CHANNEL_IN_ZFB);
        orderUpdateInfoParam.setTakingStatus(NORMAL_PICKING_ORDER);
        orderUpdateInfoParam.setGmtPay(LocalDateTime.now());
        orderService.updateInfoById(queryResult.getId(), orderUpdateInfoParam);
        //更新桌台状态
        TableUpdateInfoParam tableUpdateInfoParam = new TableUpdateInfoParam();
        tableUpdateInfoParam.setIsAvailable(TABLE_IS_AVAILABLE);
        tableService.updateInfoById(queryResult.getTableId(), tableUpdateInfoParam);

        return "支付完成，请返回订单页查看订单状态！";
    }

}
